import React, { Component } from 'react';
import Taro from '@tarojs/taro';
import {connect} from 'react-redux';
import {View} from '@tarojs/components';
import {GetRequest} from "../../../../utils/tools";
import {http} from "../../../../utils/http";
import {TARO_ENV} from "../../../../constants/api";
import "./index.scss";

export default class MapContainer extends Component {
    state: {
        map: any,
        center: any,
        bounds: any,
        marker: any,
        markerLabel: any,
        markerArr: array,
        infoWindow: any,
        tileImgLayer: array
    } = {
        map: null,
        center: null,
        bounds: null,
        marker: null,
        markerLabel: null,
        markerArr: [],
        infoWindow: null,
        tileImgLayer: []
    }

    async UNSAFE_componentWillMount() {
        if(TARO_ENV === 'h5') {
            //
        }else {
            //
        }
    }
    componentDidMount() {
        const { scenicDetail, boundary, tileImgs } = this.props;
        this.props.getMapNavigation && this.props.getMapNavigation(this);
        this.initMap(scenicDetail, boundary, tileImgs);
    }
    componentWillUnmount() {
        this.state.map && this.state.map.destroy();
    }

    // 计算地图中心
    calcMapCenterByBoundary(boundary) {
        const path = [
            boundary.getSouthWest(),
            boundary.getSouthEast(),
            boundary.getNorthEast(),
            boundary.getNorthWest()
        ];
        const position = new TMap.geometry.computeCentroid(path);
        return position;
    }
    // 计算两点之间距离(单位: 米)
    calcDistanceBetweenPoint(startLat, startLng, endLat, endLng) {
        const { map } = this.state;
        const start = new TMap.LatLng(startLat, startLng), end = new TMap.LatLng(endLat, endLng);
        const pathOfPoint=[start, end];
        /*const polyline = TMap.Polyline({
            path: pathOfPoint,
            strokeColor: '#000000',
            strokeWeight: 5,
            editable:false,
            map: map
        });*/
        const distance = Math.round(TMap.geometry.computeDistance(pathOfPoint));
        return distance;
    }
    // 点是否在边界内
    pointInBoundaryOrNot(lat, lng, boundary) {
        const pos = new window.TMap.LatLng(lat, lng);
        const sw = new TMap.LatLng(boundary[1][0], boundary[0][1]);
        const ne = new TMap.LatLng(boundary[0][0], boundary[1][1]);
        const bounds = new TMap.LatLngBounds(sw, ne);
        const path = [
            bounds.getSouthWest(),
            bounds.getSouthEast(),
            bounds.getNorthEast(),
            bounds.getNorthWest()
        ];
        return TMap.geometry.isPointInPolygon(pos, path);
    }
    // set map center
    setMapCenter(lat, lng) {
        const latLng = new TMap.LatLng(lat, lng);
        this.state.map.panTo(latLng);
    }
    // init map
    initMap(scenicDetail, boundary, tileImgs) {
        if(!boundary || !Array.isArray(boundary) || boundary.length === 0) {
            Taro.showModal({
                title: '错误提示',
                content: 'boundary 不存在或不合法',
                showCancel: false,
            })
            return;
        }
        /*if(!tileImgs || !Array.isArray(tileImgs) || tileImgs.length === 0) {
            Taro.showModal({
                title: '错误提示',
                content: 'tileImgs 不存在或不合法',
                showCancel: false,
            })
            return;
        }*/

        const sw = new TMap.LatLng(boundary[1][0], boundary[0][1])
        const ne = new TMap.LatLng(boundary[0][0], boundary[1][1])
        const bounds = new TMap.LatLngBounds(sw, ne)
        const boundsCenter = this.calcMapCenterByBoundary(bounds);
        const center = new TMap.LatLng(boundsCenter.lat, boundsCenter.lng);
        const featuresList = tileImgs.length === 0 ? ['base', 'building3d', 'building2d', 'point', 'label'] : [];

        // 初始化地图
        const map = new TMap.Map("mapContainer", {
            center: center,
            minZoom: scenicDetail.map_min_level,
            maxZoom: scenicDetail.map_max_level,
            zoom: scenicDetail.map_level,
            boundary: bounds,
            viewMode: '2D',
            showControl: false,
            baseMap: {
                type: "vector",
                features: featuresList
            }
        });
        // map.setZoom(18);
        // 初始化infoWindow
        const infoWindow = new TMap.InfoWindow({
            map: map,
            position: center,
            offset: { x: 0, y: -32 }, // y值与marker-styles-anchor-y一致
            content: '',
            enableCustom: true
        });
        infoWindow.close();

        const domNodes = document.querySelector('.map-container').childNodes;
        const logoCopy = domNodes[1].childNodes[1];
        logoCopy.remove() // 删除logo & 版权

        this.setState({ map, center, bounds, infoWindow }, () => {
            tileImgs.length > 0 && this.initImg(tileImgs);
            this.addMarkerAndRegistInfoWindow();
        });
    }
    // 初始化瓦片图
    initImg(tileImgs) {
        const tileImgLayer = [];
        const { map, bounds } = this.state;
        const { boundary } = this.props;
        this.setState({ tileImgLayer: [] });

        // 定义地图范围
        const sw = new TMap.LatLng(boundary[1][0], boundary[0][1]);
        const ne = new TMap.LatLng(boundary[0][0], boundary[1][1]);
        const minlongitude = boundary[1][0];
        const minlatitude = boundary[0][1];
        const maxlongitude = boundary[0][0];
        const maxlatitude = boundary[1][1];
        const map_imgsArr = tileImgs.reverse();
        // 1 2 0 1 2 0 1 2 0
        const arrlength = map_imgsArr.length;
        const sprtNum = Math.sqrt(arrlength); // 总瓦片数的平方根

        /**
        * (maxlongitude - minlongitude) / sprtNum : 最大最小的差值 除以 总数的平方根, 得到一张瓦片的值
        * 乘以 当前行号/当前列号: 得到 当前行/当前列 的值
        **/
        for (let i = 0; i < arrlength; i++) {
            // 余数
            let num = (i + 1) % sprtNum;
            // 若为零取平方根
            if (num === 0) num = sprtNum;
            // 总共列数
            const column = arrlength / sprtNum;
            // 当前行数
            const row = (i + 1 - num) / sprtNum + 1;

            const sw = new TMap.LatLng(
                minlongitude + ((maxlongitude - minlongitude) / sprtNum) * (row - 1),
                maxlatitude - ((maxlatitude - minlatitude) / sprtNum) * num
            );
            const ne = new TMap.LatLng(
                minlongitude + ((maxlongitude - minlongitude) / sprtNum) * row,
                maxlatitude - ((maxlatitude - minlatitude) / sprtNum) * (num - 1)
            );
            const boundaries = new TMap.LatLngBounds(sw, ne);
            const ground = new TMap.ImageGroundLayer({
                map: map,
                visible: true, // false 时，需要执行 drawImg 方法
                zIndex: 1000000,
                src: `${map_imgsArr[i]}`,
                bounds: boundaries,
                minZoom: 1,
                maxZoom: 21
            });

            tileImgLayer.push(ground);
        }
        this.setState({ tileImgLayer });
    }
    // show | hide tile
    hideTiles = flag => {
        const { map, tileImgLayer } = this.state;
        tileImgLayer.map(item => {
            item.setVisible(flag);
        });
        if(!flag) {
            map.setBaseMap({type: "vector", features: ['base', 'building3d', 'building2d', 'point', 'label']});
        }else {
            map.setBaseMap({type: "vector", features: []});
        }
    };

    // 视频
    handlePlayVideo(e) {
        this.props.handlePlayVideo(e);
    }
    // 解说
    handleCommentary(e) {
        this.props.handleCommentary(e);
    }
    // 导航
    handleLocateWalk(e) {
        // this.props.handleLocateWalk(e);
        this.props.handleLocateWalk(e, "end"); // 自动选为终点
    }
    // 详情
    handleViewDetail(e) {
        this.props.handleViewDetail(e);
    }
    //设置自适应显示marker
    fitMarkers() {
        const { map, markerArr } = this.state;
        const bounds = new TMap.LatLngBounds();

        //判断标注点是否在范围内
        markerArr.map(item => {
            //若坐标点不在范围内，扩大bounds范围
            if(bounds.isEmpty() || !bounds.contains(item.position)) {
                bounds.extend(item.position);
            }
        })
        //设置地图可视范围
        map.fitBounds(bounds, {
            padding: 50 // 自适应边距
        });
        // 数据量2个以内
        if(markerArr.length < 3) {
            map.setZoom(11);
        }else if(markerArr.length > 5) {
            map.setZoom(13.3);
        }
    }
    // ready open info window
    readyOpenInfoWindow(scenicInfo, time) {
        setTimeout(() => {
            this.getCurrentScenicInfoWindow(scenicInfo);
        }, time);
    }
    // get current scenicInfo window
    getCurrentScenicInfoWindow(scenicInfo) {
        const { markerArr } = this.state;
        const markerObj = markerArr.find(item => item.properties.id === scenicInfo.id);
        const windowObj = { geometry: markerObj };
        this.openInfoWindow(windowObj);
    }
    // open infoWindow
    openInfoWindow(e) {
        const _this = this;
        const { infoWindow } = this.state;
        const { id, position, properties } = e.geometry;
        const btn1 = `commentary_${id}`, btn2 = `locate_${id}`, btn3 = `detail_${id}`;
        const styleObj = {
            box: "font-size: 14px; color: #666; position: relative;",
            title: "font-size: 15px; text-align: left; position: absolute; top: -18px;",
            cntBox: "display: flex; align-items: center; padding-top: 7px;",
            imgBox: "width: 90px; height: 90px;",
            infoImg: "position: relative; display: inline-block; width: inherit; height: inherit;",
            playIcon: "position: absolute; width: 36px; top: 50%; left: 50%; transform: translate(-50%, -50%);",
            img: "width: 100%; height: 100%; border-radius: 4px;",
            iconBox: "width: 30px; height: 30px;",
            icon: "width: 100%; height: 100%;",
            boxRight: "flex: 1; display: flex; flex-direction: column; width: 200px; height: 90px; overflow: hidden; text-align: left; padding-left: 10px;",
            rightDesc: "flex: 1; max-height: 37px; white-space: normal; word-break: break-all; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;",
            infoLink: "color: #F3B24C; font-size: 12px; margin-top: 3px;",
            infoLinkA: "color: inherit;",
            btnBox: "margin-top: 7px;",
            btn: `
                display: inline-block;
                background-color: #F8DE4C;
                font-size: 12px;
                padding: 5px 15px;
                border-radius: 3px;
                margin-right: 10px;
            `
        };

        const hasVideo = !!properties.video_photo_url && !!properties.video_url;
        const infoImg = properties.video_photo_url && properties.video_url ? properties.video_photo_url : properties.photo_url;
        const infoImgHTML = hasVideo ?
            `
                <span style="${styleObj.infoImg}">
                    <img id="infoPlayVideo" src="https://resource.ivcheng.com/upload/images/20220909/1662708461901_256.png" style="${styleObj.playIcon}" />
                    <img src='${infoImg}' style="${styleObj.img}" />
                </span>
            `
            :
            `<img src='${infoImg}' style="${styleObj.img}" />`;
        const commentaryHTML = properties.audio_url !== "" ?
            `<span id="${btn1}" style="${styleObj.btn}">解说</span>`
            :
            "";
        // 景点类
        const contentScenic = `
            <div style="${styleObj.box}">
                <div style="${styleObj.title}">${properties.name}</div>
                <div style="${styleObj.cntBox}">
                    <div style="${styleObj.imgBox}">
                        ${infoImgHTML}
                    </div>
                    <div style="${styleObj.boxRight}">
                        <div style="${styleObj.rightDesc}">${properties.scenic_remark || properties.remark}</div>
                        <div style="${styleObj.infoLink}">
                            <span id="${btn3}" style="${styleObj.infoLinkA}">详情</span>
                        </div>
                        <div style="${styleObj.btnBox}">
                            ${commentaryHTML}
                            <span id="${btn2}" style="${styleObj.btn}">导航</span>
                        </div>
                    </div>
                </div>
            </div>
        `;
        // 非景点类
        const contentOther = `
            <div style="${styleObj.box}">
                <div style="${styleObj.cntBox}">
                    <div style="${styleObj.iconBox}">
                        <img src='${properties.icon}' style="${styleObj.icon}" />
                    </div>
                    <div style="${styleObj.rightDesc}">
                        <span style="padding: 0 15px;">${properties.name}</span>
                        <span id="${btn2}" style="${styleObj.btn}">导航</span>
                    </div>
                </div>
            </div>
        `;
        const contentHTML = !properties.type ? contentScenic : contentOther;

        infoWindow.open();
        infoWindow.setPosition(position);//设置信息窗位置
        infoWindow.setContent(contentHTML);//设置信息窗内容
        this.setMapCenter(position.lat, position.lng);
        // 视频
        if(hasVideo) {
            document.getElementById("infoPlayVideo").addEventListener("click", function() {
                _this.handlePlayVideo(e);
            });
        }
        // 解说(仅限景点类)
        if(!properties.type && commentaryHTML) {
            document.getElementById(btn1).addEventListener("click", function() {
                _this.handleCommentary(e);
            });
        }
        // 导航
        document.getElementById(btn2).addEventListener("click", function() {
            _this.handleLocateWalk(e);
        });
        // 详情(仅限景点类)
        if(!properties.type) {
            document.getElementById(btn3).addEventListener("click", function() {
                _this.handleViewDetail(e);
            });
        }
    }
    /**
    * add marker & regist infoWindow
    *
    * @param type 标注类型
    **/
    addMarkerAndRegistInfoWindow(type) {
        type = type || "";
        const _this = this;
        const { scenicList: markers } = this.props;
        const { map, center } = this.state;
        if(markers.length === 0) return;

        const result = this.createMarker(markers);
        const { tempMarkers, tempLabels, markerStyleHash, labelStyleHash } = result;
        //初始化marker
        const marker = new TMap.MultiMarker({
            id: 'marker-layer',
            map: map,
            styles: markerStyleHash,
            geometries: tempMarkers
        });

        //初始化label
        const markerLabel = new TMap.MultiLabel({
            id: 'label-layer',
            map: map,
            styles: labelStyleHash,
            geometries: tempLabels
        });

        // marker click
        marker.on("click", e => {
            _this.openInfoWindow(e);
        });
        // map.setZoom(15);

        setTimeout(() => {
            this.setState({ marker, markerLabel, markerArr: [...tempMarkers] }, () => {
                this.fitMarkers();
            });
        }, 0)
    }
    // 添加marker
    addMarkers(type, markers) {
        if(!this.state.marker) return;
        this.removeMarker();
        if(markers.length === 0) return;

        type = type || "";
        const _this = this;
        const { map, center, marker, markerLabel } = this.state;

        const result = this.createMarker(markers);
        const { tempMarkers, tempLabels, markerStyleHash, labelStyleHash } = result;
        //设置marker
        marker.setMap(map);
        marker.setGeometries(tempMarkers); // 更新标注点数据
        marker.setStyles(markerStyleHash); // 更新标注点样式
        markerLabel.setMap(map);
        markerLabel.setGeometries(tempLabels); // 更新文本数据
        markerLabel.setStyles(labelStyleHash); // 更新文本样式

        marker.on("click", e => {
            _this.openInfoWindow(e);
        });
        // map.setZoom(15);

        setTimeout(() => {
            this.setState({ markerArr: [...tempMarkers] }, () => {
                this.fitMarkers();
            });
        }, 0)
    }
    // creaker marker
    createMarker(markers) {
        const tempMarkers = [];
        const tempLabels = [];

        let markerStyleHash = {},
            labelStyleHash = {};

        markers.map((item, index) => {
            const labelWidth = item.length * 15;

            const markerObj = {
                id: `marker_${item.id}`,
                styleId: `markerStyle_${item.id}`, // 不同标注对应不同styleId
                position: new TMap.LatLng(item.lat, item.lng),
                properties: {
                    ...item,
                    idx: index + 1
                }
            };
            const markerStyleObj = {
                [`markerStyle_${item.id}`]: new TMap.MarkerStyle({
                    width: 48,
                    height: 48,
                    anchor: { x: 24, y: 45 },
                    src: item.iconMarker
                })
            };

            const labelObj = {
                id: `label_${item.id}`,
                styleId: `labelStyle_${item.id}`,
                position: new TMap.LatLng(item.lat, item.lng),
                content: item.name.length > 5 ? item.name.slice(0, 5) : item.name,
                properties: {
                    ...item,
                    idx: index + 1
                }
            };
            const labelStyleObj = {
                [`labelStyle_${item.id}`]: new TMap.LabelStyle({
                    width: item.name.length > 5 ? 5 * 14 : item.name.length * 14,
                    height: 18,
                    color: '#333', //颜色属性
                    size: 12, //文字大小属性
                    offset: { x: 0, y: 15 }, //文字偏移属性单位为像素
                    angle: 0, //文字旋转属性
                    alignment: 'center', //文字水平对齐属性
                    verticalAlignment: 'middle', //文字垂直对齐属性
                    backgroundColor: "#fff",
                    borderWidth: 1,
                    borderRadius: 4,
                    borderColor: "#F4A52C"
                })
            };

            tempMarkers.push(markerObj);
            tempLabels.push(labelObj);
            markerStyleHash = Object.assign({}, markerStyleHash, markerStyleObj);
            labelStyleHash = Object.assign({}, labelStyleHash, labelStyleObj);
        });

        return { tempMarkers, tempLabels, markerStyleHash, labelStyleHash };
    }
    // creaker label
    createLabel() {
        const tempLabels = [];
        let labelStyleHash = {};
    }
    // remove marker and label
    removeMarker() {
        const { map, marker, markerLabel, infoWindow } = this.state;
        if(marker) {
            marker.off("click", e => {
                _this.openInfoWindow(e);
            });
            marker.setMap(null);
        }
        if(markerLabel) {
            markerLabel.setMap(null);
        }
        if(infoWindow) {
            infoWindow.close();
        }
    }

    render() {
        return (
            <View id="mapContainer" className="map-container"></View>
        )
    }
}
